package com.panopset.db;

import java.sql.Connection;

/**
 * Call setConnectionSupplier before using Briefcase.
 *
 * @author Karl Dinwiddie
 *
 */
public final class ConnectionManager {

    /**
     * Database connection information.
     */
    private ConnectionSupplier cs;

    /**
     * Cached connection.
     */
    private Connection conn;

    /**
     * This method must be called before getConnection() is called.
     *
     * @param connectionSupplier
     *            ConnectionSupplier.
     */
    public static void setConnectionSupplier(
            final ConnectionSupplier connectionSupplier) {
        getInstance().cs = connectionSupplier;
    }

    /**
     *
     * @return An open connection.
     */
    public static Connection getConnection() {
        return getInstance().getConn();
    }

    /**
     * If the connection is closed, a new Connection is obtained from the
     * ConnectionSupplier.
     *
     * @return An open connection.
     */
    private Connection getConn() {
        try {
            if (conn == null) {
                conn = cs.getConnection();
            }
            if (conn.isClosed()) {
                conn = cs.getConnection();
            }
            return conn;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * Based on SingletonHolder inner class by Bill Pugh.
     *
     *
     * <h5>References</h5>
     * <ul>
     * <li>
     * <a href="http://en.wikipedia.org/wiki/Singleton_pattern">
     * http://en.wikipedia.org/wiki/Singleton_pattern </a></li>
     * </ul>
     *
     */
    private static final class Singleton {
        /**
         * Instance variable.
         */
        private static final ConnectionManager INSTANCE

        = new ConnectionManager();

        /**
         * Private constructor.
         */
        private Singleton() {
            // Prevent instantiation.
        }
    }

    /**
     * @return static ConnectionManager instance.
     */
    private static ConnectionManager getInstance() {
        return Singleton.INSTANCE;
    }

    /**
     * Private singleton constructor.
     */
    private ConnectionManager() {
        // Prevent outside instantiation.
    }
}
